package cn.virens.mybatis.mapper.example;

import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;

import cn.virens.common.exception.APIException;
import cn.virens.mybatis.mapper.example.base.AbstractExample;

@SuppressWarnings("serial")
public class Example extends AbstractExample {
	private Example() {
	}

	public ExampleCriteria or() throws APIException {
		return addCriteria(new ExampleCriteria(true));
	}

	public ExampleCriteria and() throws APIException {
		return addCriteria(new ExampleCriteria(false));
	}

	public void or(Consumer<ExampleCriteria> consumer) throws APIException {
		consumer.accept(addCriteria(new ExampleCriteria(true)));
	}

	public void and(Consumer<ExampleCriteria> consumer) throws APIException {
		consumer.accept(addCriteria(new ExampleCriteria(false)));
	}

	public ExampleHaving havingOr(String condition) {
		return addHaving(new ExampleHaving(true, condition));
	}

	public ExampleHaving havingOr(String condition, Object value1) {
		return addHaving(new ExampleHaving(true, condition, value1));
	}

	public ExampleHaving havingOr(String condition, Object value1, Object value2) {
		return addHaving(new ExampleHaving(true, condition, value1, value2));
	}

	public ExampleHaving havingAnd(String condition) {
		return addHaving(new ExampleHaving(false, condition));
	}

	public ExampleHaving havingAnd(String condition, Object value1) {
		return addHaving(new ExampleHaving(false, condition, value1));
	}

	public ExampleHaving havingAnd(String condition, Object value1, Object value2) {
		return addHaving(new ExampleHaving(false, condition, value1, value2));
	}

	public ExampleJoin left(String table, Consumer<ExampleJoin> consumer) {
		ExampleJoin answer = addJoin(new ExampleJoin("LEFT", table));

		consumer.accept(answer);

		return answer;
	}

	public ExampleJoin inner(String table, Consumer<ExampleJoin> consumer) {
		ExampleJoin answer = addJoin(new ExampleJoin("INNER", table));

		consumer.accept(answer);

		return answer;
	}

	public static Example newInstance() {
		return new Example();
	}

	public static Example of(String key, Object value) {
		Example example = new Example();

		example.and().andEqualTo(key, value);

		return example;
	}

	public static Example of(Map<String, Object> map) {
		Example example = new Example();

		ExampleCriteria criteria = example.and();

		for (Entry<String, Object> entry : map.entrySet()) {
			criteria.andEqualTo(entry.getKey(), entry.getValue());
		}

		return example;
	}

}
